package com.example.hoasbackend.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.hoasbackend.common.IndentOperationType;
import com.example.hoasbackend.common.IndentState;
import com.example.hoasbackend.common.utls.RedisUtil;
import com.example.hoasbackend.common.utls.DateTimeUtil;
import com.example.hoasbackend.mapper.IndentMapper;
import com.example.hoasbackend.model.AO.CreateIndentBatchAO;
import com.example.hoasbackend.model.AO.ModifyCheckTimeAO;
import com.example.hoasbackend.model.VO.CreateIndentBatchVO;
import com.example.hoasbackend.model.VO.GetIndentBatchVO;
import com.example.hoasbackend.model.domain.RoomType;
import com.example.hoasbackend.model.dto.IndentDetailBO;
import com.example.hoasbackend.model.dto.IndentRedis;
import com.example.hoasbackend.service.IndentOperationService;
import com.example.hoasbackend.service.SnowFlakeService;
import com.relops.snowflake.Snowflake;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.hoasbackend.common.JsonResponse;
import com.example.hoasbackend.service.IndentService;
import com.example.hoasbackend.model.domain.Indent;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;


/**
 *
 *  前端控制器
 *
 *
 * @author lhx
 * @since 2022-03-03
 * @version v1.0
 */
@Controller
@RequestMapping("/api/indent")
public class IndentController {

    private final Logger logger = LoggerFactory.getLogger( IndentController.class );
    @Autowired
    private IndentMapper indentMapper;
    @Autowired
    private IndentService indentService;

    @Autowired
    private SnowFlakeService snowFlakeService;

    @Autowired
    private IndentOperationService indentOperationService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    DateTimeUtil dateTimeUtil;

    /**
    * 描述：根据Id 查询
    *
    */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    public JsonResponse getById(@PathVariable("id") Long id)throws Exception {
        Indent  indent =  indentService.getById(id);
        return JsonResponse.success(indent);
    }

    /**
    * 描述：根据Id删除
    *
    */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public JsonResponse deleteById(@PathVariable("id") Long id) throws Exception {
        indentService.removeById(id);
        return JsonResponse.success(null);
    }


    /**
    * 描述：根据Id 更新
    *
    */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseBody
    public JsonResponse updateIndent(@PathVariable("id") Long  id,Indent  indent) throws Exception {
        indent.setId(id);
        indentService.updateById(indent);
        return JsonResponse.success(null);
    }


    /**
    * 描述:创建Indent
    *
    */
    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse create(Indent  indent) throws Exception {
        indentService.save(indent);
        return JsonResponse.success(null);
    }


    /**
     * 描述:新建订单组接口
     * 0. 补充indent信息
     * 1. 将indentbatch分解成多个indent
     * 2. 创建indent
     * 2.1存储indent
     * 2.2创建indentOperation
     * 2.3设定checkinout日期
     */
    @RequestMapping(value = "/batch", method = RequestMethod.POST)
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse createIndentBatch(
            @RequestBody CreateIndentBatchAO createIndentBatchAO/*,@RequestHeader("Authorization") String token*/
    ) throws Exception {
        long userId/*=getUserIdfromToken(token)*/ = createIndentBatchAO.getUserId();
        Snowflake idWorker = SnowFlakeService.idWorker;
        long batchId=idWorker.next();
        String checkInTimeString=createIndentBatchAO.getCheckInTime();
        String checkOutTimeString=createIndentBatchAO.getCheckOutTime();
        //turn AO to indent
        Indent indentBasicInfo = indentService.turnCreateIndentBatchAOToIndent(createIndentBatchAO,userId,batchId);
        System.out.println("HERE IS HOTEL ID");
        System.out.println(createIndentBatchAO.getHotelId());
        System.out.println(indentBasicInfo.getHotelId());
//save indent batch & op to mysql  && prepare for output(gentime result)
        List<Indent> indentBatch = indentService.splitIndentBatch(indentBasicInfo, createIndentBatchAO.getRoomNum());
        long genTime=System.currentTimeMillis();
        for (Indent indent : indentBatch) {
            Indent ind=indent;
            indentService.createIndent(ind,checkInTimeString,checkOutTimeString);
        }
        CreateIndentBatchVO result=new CreateIndentBatchVO(batchId,genTime);
//save indent to redis
        IndentRedis indentRedis=new IndentRedis(batchId,
                dateTimeUtil.stringtoDateTime(checkInTimeString), dateTimeUtil.stringtoDateTime(checkOutTimeString)
        ,indentOperationService.getExpirationDuration(batchId,IndentState.CREATED),IndentState.CREATED);
        indentService.saveRedisIndent(indentRedis);

        return JsonResponse.success(result).setCode(200);
    }

    /**
     *取消订单
     */
    @RequestMapping(value = "/batch", method = RequestMethod.DELETE)
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse cancelIndentBatch(long batchId){

        List<Indent> toCancelIndentBatch=indentService.getListByBatchId(batchId);
        for(Indent indent:toCancelIndentBatch){
            indentOperationService.createIndentOperation(
                    indent.getId(), IndentOperationType.CANCEL,null,indent.getUserId(),indent.getUserId()
            );
        }
        redisUtil.set(batchId+"","CountingDown",RedisUtil.NOT_EXPIRE);
        redisUtil.set(batchId+":state",IndentState.CANCELED);
        return JsonResponse.success(null).setCode(200);
    }

    /**
     *支付订单
     */
    @RequestMapping(value = "/batch", method = RequestMethod.PATCH)
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse payIndentBatch (Long batchId){
//        if(alipay().success){
//            以下内容在此
//        }
        List<Indent> toPaidIndentBatch = indentService.getListByBatchId(batchId);
        for(Indent indent:toPaidIndentBatch){
            indentOperationService.createIndentOperation(
                    indent.getId(), IndentOperationType.PAY,null,indent.getUserId(),indent.getUserId()
            );
        }
        redisUtil.set(batchId+"","CountingDown",indentOperationService.getExpirationDuration(batchId,IndentState.PAID));
        redisUtil.set(batchId.toString()+":state", IndentState.PAID);
        return JsonResponse.success(null).setCode(200);
    }

    /**
     *获取订单
     * 1.获取前端传来的batchId
     * 2.根据batchId获得indent list
     * 3.00增加一个DTO,作为返回的result list
     * 对于每一个indent:
     * 3.1 获得其当前订单状态
     * 3.2 获得其创建订单的时间,也就是created op的创建时间
     * 3.3 获得入住和登出时间,也就是寻找created和MOD IFYDATE操作之中最新的记录的data
     * 3.4获得totalamount,也就是所有的价格相加
     * 100.返回
     */
    @RequestMapping(value = "/batch", method = RequestMethod.GET)
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse getIndentBatch (long batchId){
        return JsonResponse.success(indentService.getIndentBatch(batchId));

    }
    /**
     *支付订单
     * 暂时只做了不允许checkintime比今天小的处理
     * 1.生成operation
     * 2. 修改redis
     */
    @RequestMapping(value = "/batch/checktime", method = RequestMethod.PUT )
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse modifyCheckTime (@RequestBody ModifyCheckTimeAO modifyCheckTimeAO){
        long batchId=modifyCheckTimeAO.getBatchId();
        LocalDateTime checkInTime=dateTimeUtil.stringtoDateTime(modifyCheckTimeAO.getCheckInTime());
        LocalDateTime checkOutTime=dateTimeUtil.stringtoDateTime(modifyCheckTimeAO.getCheckOutTime());

        String errmsg=dateTimeUtil.timeCheck(checkInTime,checkOutTime);
        if(!errmsg.equals("")){
            return JsonResponse.failure(errmsg).setCode(400);
        }
        List<Indent> indentBatch=indentService.getListByBatchId(batchId);
        for(Indent indent:indentBatch){
            indentOperationService.createIndentOperation(indent.getId(),IndentOperationType.MODIFYDATE,
                    dateTimeUtil.dateTimetoString(checkInTime)+";"+dateTimeUtil.dateTimetoString(checkOutTime),
                    indent.getUserId(),indent.getUserId());
        }
        redisUtil.set(batchId+":checkintime",dateTimeUtil.dateTimetoString(checkInTime));
        redisUtil.set(batchId+":checkouttime",dateTimeUtil.dateTimetoString(checkOutTime));
        return JsonResponse.success(null).setCode(200);
    }


    @RequestMapping(value = "/userbatch", method = RequestMethod.GET )
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse getIndentBatchListByUserId (Long userId){
        QueryWrapper<Indent> wrapper=new QueryWrapper<Indent>().eq("user_id",userId);
        List<Indent> indentListOfUser=indentMapper.selectList(wrapper);
        HashSet<Long> batchIdSetOfUser=new HashSet<>();
        for(Indent indent:indentListOfUser){
            if(!batchIdSetOfUser.contains(indent.getBatchId())){
                batchIdSetOfUser.add(indent.getBatchId());
            }
        }
        List<GetIndentBatchVO> indentBatchVOList=new ArrayList<>();
        for(Long batchId:batchIdSetOfUser){
            indentBatchVOList.add(indentService.getIndentBatch(batchId));
        }
        return JsonResponse.success(indentBatchVOList);


    }
    @RequestMapping(value = "/test", method = RequestMethod.GET )
//    @RequestMapping(value = "/cib", method = RequestMethod.POST)
    @ResponseBody
    public JsonResponse getIndentBatchIdListByUserId (Long userId){
        QueryWrapper<Indent> wrapper=new QueryWrapper<Indent>().eq("user_id",userId);
        List<Indent> indentListOfUser=indentMapper.selectList(wrapper);
        HashSet<Long> batchIdSetOfUser=new HashSet<>();
        for(Indent indent:indentListOfUser){
            if(!batchIdSetOfUser.contains(indent.getBatchId())){
                batchIdSetOfUser.add(indent.getBatchId());
            }
        }

//        QueryWrapper<Indent> wrapper=new QueryWrapper<Indent>().eq("user_id",userId);
//        wrapper.groupBy("batch_id").select("batch_id");
//        List<Indent> indentListOfUser=indentMapper.selectList(wrapper);
//        return JsonResponse.success(indentListOfUser);



        List<GetIndentBatchVO> indentBatchVOList=new ArrayList<>();
        for(Indent indent:indentListOfUser){
            indentBatchVOList.add(indentService.getIndentBatch(indent.getBatchId()));
        }
        return JsonResponse.success(indentBatchVOList);




//        for(Long batchId:batchIdSetOfUser){
//            indentBatchVOList.add(indentService.getIndentBatch(batchId));
//        }
//        return JsonResponse.success(indentBatchVOList);


    }
}

